#include <stdio.h>
#include "s3c24xx.h"

#define PCLK        50000000
#define S3C2410_TCFG_PRESCALER0_MASK (255<<0)
#define S3C2410_TCFG1_MUX0_DIV2   (0<<0)
#define S3C2410_TCFG1_MUX0_DIV4   (1<<0)
#define S3C2410_TCFG1_MUX0_DIV8   (2<<0)
#define S3C2410_TCFG1_MUX0_DIV16  (3<<0)
#define S3C2410_TCFG1_MUX0_TCLK0  (4<<0)
#define S3C2410_TCFG1_MUX0_MASK   (15<<0)

#define GPB0_tout0  (2<<(0*2))
#define GPB0_out    (1<<(0*2))
#define GPB1_out    (1<<(1*2))

#define GPB0_MSK    (3<<(0*2))
#define GPB1_MSK    (3<<(1*2))


/* freq:  pclk/50/16/65536 ~ pclk/50/16 
  * if pclk = 12MHz, freq is 1Hz to 15000Hz
  * human ear : 20Hz~ 20000Hz
  */
void PWM_Init( unsigned long freq )
{
  unsigned long tcon;
  unsigned long tcnt;
  unsigned long tcfg1;
  unsigned long tcfg0;

  //set GPB0 as tout0, pwm output
  GPBCON &= ~GPB0_MSK;
  GPBCON |= GPB0_tout0; 

  tcfg0 = TCFG0;
  tcfg1 = TCFG1;
  tcon = TCON;

  //prescaler = 50
  tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
  tcfg0 |= (50 - 1); 

  //mux = 1/16
  tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
  tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;

  TCFG0 = tcfg0;
  TCFG1 = tcfg1;

  tcnt  = (PCLK/50/16)/freq;
  
  TCNTB0 = tcnt;
  TCMPB0 = tcnt/2;
        
  tcon &= ~0x1f;
  tcon |= 0xb;    //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
  TCON = tcon;
  
  tcon &= ~2;     //clear manual update bit
  TCON = tcon;
}


void PWM_Stop( void )
{
	//set GPB0 as output
	//set GPB0 as tout0, pwm output
	GPBCON &= ~GPB0_MSK;
	GPBCON |= GPB0_out; 
}

